/*
 * *****************************************************************************
 *  Copyright ( c ) 2019 huibur Inc. All Rights Reserved.
 *
 *  This software is the confidential and proprietary information of Huibur Inc
 *  (*Confidential Information*). You shall not disclose such Confidential Information
 *  and shall use it only in accordance with the terms of the license agreement
 *  you entered into with Huibur or a Huibur authorized
 *  reseller (the "License Agreement*).
 *  ******************************************************************************
 */

package com.huibur.devicecheck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huibur.devicecheck.enums.DeviceEnums;
import com.huibur.devicecheck.enums.TypeEnums;
import com.huibur.devicecheck.mapper.*;
import com.huibur.devicecheck.model.param.DeviceParam;
import com.huibur.devicecheck.model.po.*;
import com.huibur.devicecheck.model.query.DeviceQuery;
import com.huibur.devicecheck.model.vo.DeviceVO;
import com.huibur.devicecheck.request.ObjRes;
import com.huibur.devicecheck.request.PageRes;
import com.huibur.devicecheck.request.SessionContext;
import com.huibur.devicecheck.service.IDeviceService;
import com.huibur.devicecheck.utils.ConvertPageUtil;
import com.huibur.devicecheck.utils.DateUtils;
import com.huibur.devicecheck.utils.ExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/*******************************************************
* Title: DeviceServiceImpl.java
* Description:
* @author baiqingshuo
* @date 2021/9/24
* @version 1.0
*******************************************************/
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, DevicePO> implements IDeviceService {

    @Autowired
    DeviceMapper deviceMapper;
    @Autowired
    TaskRecordMapper taskRecordMapper;
    @Autowired
    DeviceCategoryMapper deviceCategoryMapper;
    @Autowired
    TypeMapper typeMapper;
    @Autowired
    CheckLocationMapper checkLocationMapper;
    @Autowired
    AssignTaskMapper assignTaskMapper;
    @Autowired
    SysParamsMapper sysParamsMapper;

    /**
     * 新增设备
     *
     * @param deviceParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> insertDevice(DeviceParam deviceParam) {

        //设备唯一标识生成规则
        String label = UUID.randomUUID().toString().replaceAll("-", "");

        DevicePO devicePO = new DevicePO();
        devicePO.setDeviceCategoryId(deviceParam.getDeviceCategoryId());
        devicePO.setLabel(label);
        devicePO.setModel(deviceParam.getModel());
        devicePO.setManufacturer(deviceParam.getManufacturer());
        devicePO.setStorePlaceId(deviceParam.getStorePlaceId());
        devicePO.setPurchaseAt(deviceParam.getPurchaseAt());
        devicePO.setImage(deviceParam.getImage());
        devicePO.setIsDeleted(0);
        devicePO.setCreateAt(DateUtils.getCurrentTimestamp());
        devicePO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
        deviceMapper.insert(devicePO);
        return new ObjRes<Void>().success("创建成功");
    }

    /**
     * 批量新增
     * @param deviceParam
     * @return
     */
    @Override
    public ObjRes<Void> saveBatchDevice(DeviceParam deviceParam) {
        List<DevicePO> devicePOList = new ArrayList<>();
        for (int i = 0; i < deviceParam.getCount(); i++) {
            //设备唯一标识生成规则
            String label = UUID.randomUUID().toString().replaceAll("-", "");

            DevicePO devicePO = new DevicePO();
            devicePO.setDeviceCategoryId(deviceParam.getDeviceCategoryId());
            devicePO.setLabel(label);
            devicePO.setModel(deviceParam.getModel());
            devicePO.setManufacturer(deviceParam.getManufacturer());
            devicePO.setStorePlaceId(deviceParam.getStorePlaceId());
            devicePO.setPurchaseAt(deviceParam.getPurchaseAt());
            devicePO.setImage(deviceParam.getImage());
            devicePO.setIsDeleted(0);
            devicePO.setCreateAt(DateUtils.getCurrentTimestamp());
            devicePO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
            devicePOList.add(devicePO);
        }
        this.saveBatch(devicePOList);
        return new ObjRes<Void>().success("创建成功");    }

    /**
     * 删除设备
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        DevicePO devicePO = new DevicePO();
        devicePO.setId(id);
        devicePO.setIsDeleted(DeviceEnums.DELETE.getCode());
        deviceMapper.updateById(devicePO);
        return true;
    }

    /**
     * 编辑设备
     *
     * @param id
     * @param deviceParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> updateDevice(Long id, DeviceParam deviceParam) {
        DevicePO devicePO = new DevicePO();
        devicePO.setId(id);
        devicePO.setDeviceCategoryId(deviceParam.getDeviceCategoryId());
        devicePO.setModel(deviceParam.getModel());
        devicePO.setManufacturer(deviceParam.getManufacturer());
        devicePO.setStorePlaceId(deviceParam.getStorePlaceId());
        devicePO.setPurchaseAt(deviceParam.getPurchaseAt());
        devicePO.setImage(deviceParam.getImage());
        devicePO.setIsDeleted(0);
        devicePO.setUpdateAt(DateUtils.getCurrentTimestamp());
        devicePO.setUpdateBy(SessionContext.getCurrentUserSubject().getUserId());
        deviceMapper.updateById(devicePO);
        return new ObjRes<Void>().success("修改成功");
    }

    /**
     * 设备列表(查询并分页)
     *
     * @param deviceQuery
     * @return
     */
    @Override
    public PageRes<DeviceVO> selectDeviceList(DeviceQuery deviceQuery) {
        Page<DevicePO> page = new Page<>(deviceQuery.getCurrent(), deviceQuery.getPageSize());
        IPage<DeviceVO> pages = deviceMapper.selectDeviceList(page, deviceQuery);
        return ConvertPageUtil.convertPage(deviceQuery.getCurrent(), pages.getTotal(), pages.getRecords());
    }

    /**
     * 获取设备详情
     *
     * @param id
     * @return
     */
    @Override
    public DeviceVO selectDeviceById(Long id) {
        DevicePO device = deviceMapper.selectOne(new LambdaQueryWrapper<DevicePO>()
                .eq(DevicePO::getId, id));
        Long deviceCategoryId = device.getDeviceCategoryId();
        DeviceCategoryPO deviceCategory = deviceCategoryMapper.selectOne(new LambdaQueryWrapper<DeviceCategoryPO>()
                .eq(DeviceCategoryPO::getId, deviceCategoryId));

        CheckLocationPO checkLocationPO = checkLocationMapper.selectOne(new LambdaQueryWrapper<CheckLocationPO>()
                .eq(CheckLocationPO::getId, device.getStorePlaceId())
                .eq(CheckLocationPO::getIsDeleted, 0));

        List<String> locationList = new ArrayList<>();
        String route = checkLocationPO.getRoute();
        String[] split = route.split("\\|");
        for (String s : split) {
            if (StringUtils.hasText(s)) {
                locationList.add(s);
            }
        }

        DeviceVO deviceVO = new DeviceVO();
        deviceVO.setTypeId(deviceCategory.getTypeId());
        deviceVO.setName(deviceCategory.getName());
        deviceVO.setUnit(deviceCategory.getUnit());
        deviceVO.setLabel(device.getLabel());
        deviceVO.setModel(device.getModel());
        deviceVO.setManufacturer(device.getManufacturer());
        deviceVO.setStorePlaceId(device.getStorePlaceId());
        deviceVO.setPurchaseAt(device.getPurchaseAt());
        deviceVO.setImage(device.getImage());
        deviceVO.setIsDeleted(device.getIsDeleted());
        deviceVO.setCreateAt(device.getCreateAt());
        deviceVO.setCreateBy(device.getCreateBy());
        deviceVO.setStatus(device.getStatus());
        deviceVO.setLocationList(locationList);
        return deviceVO;
    }

    /**
     * 获取设备基本信息(移动端调用)
     *
     * @param label
     * @return
     */
    @Override
    public DeviceVO findDeviceByLabel(String label) {
        DevicePO device = deviceMapper.selectOne(new LambdaQueryWrapper<DevicePO>()
                .eq(DevicePO::getLabel, label)
                .ne(DevicePO::getIsDeleted, DeviceEnums.DELETE.getCode()));
        Long deviceCategoryId = device.getDeviceCategoryId();
        DeviceCategoryPO deviceCategory = deviceCategoryMapper.selectOne(new LambdaQueryWrapper<DeviceCategoryPO>()
                .eq(DeviceCategoryPO::getId, deviceCategoryId));

        DeviceVO deviceVO = new DeviceVO();
        deviceVO.setTypeId(deviceCategory.getTypeId());
        deviceVO.setName(deviceCategory.getName());
        deviceVO.setUnit(deviceCategory.getUnit());
        deviceVO.setLabel(device.getLabel());
        deviceVO.setModel(device.getModel());
        deviceVO.setManufacturer(device.getManufacturer());
        deviceVO.setStorePlaceId(device.getStorePlaceId());
        deviceVO.setPurchaseAt(device.getPurchaseAt());
        deviceVO.setImage(device.getImage());
        deviceVO.setIsDeleted(device.getIsDeleted());
        deviceVO.setCreateAt(device.getCreateAt());
        deviceVO.setCreateBy(device.getCreateBy());
        deviceVO.setStatus(device.getStatus());
        return deviceVO;


    }

    /**
     * 检查项获取设备名称
     *
     * @return
     */
    @Override
    public List<DeviceCategoryPO> selectDeviceName() {
        List<DeviceCategoryPO> deviceCategoryPOList = deviceCategoryMapper.selectList(new QueryWrapper<DeviceCategoryPO>()
                .select("distinct id,name")
                .eq("is_deleted", 0));
        if (CollectionUtils.isEmpty(deviceCategoryPOList)) {
            return null;
        }

        return deviceCategoryPOList;
    }

    /**
     * 获取生产厂家列表
     *
     * @return
     */
    @Override
    public List<String> selectDeviceManufacturer() {
        List<DevicePO> devicePOList = deviceMapper.selectList(new QueryWrapper<DevicePO>()
                .select("distinct manufacturer")
                .ne("is_deleted", DeviceEnums.DELETE.getCode()));
        if (CollectionUtils.isEmpty(devicePOList)) {
            return null;
        }
        List<String> collect = devicePOList.stream().map(e -> e.getManufacturer()).distinct().collect(Collectors.toList());
        return collect;
    }

    /**
     * 获取设备类别列表
     *
     * @return
     */
    @Override
    public List<TypePO> selectDeviceType() {
        List<TypePO> typePOList = typeMapper.selectList(new QueryWrapper<TypePO>()
                .select("distinct id,name")
                .ne("is_deleted", 1));
        if (CollectionUtils.isEmpty(typePOList)) {
            return null;
        }
//        List<String> collect = typePOList.stream().map(item -> item.getName()).distinct().collect(Collectors.toList());
        return typePOList;
    }

    /**
     * 获取某个巡检员的当前月份未检查设备
     * @param userId
     * @return
     */
    @Override
    public List<DeviceVO> selectDeviceListByUserId(Long userId) throws ParseException {
        List<AssignTaskPO> assignTaskPOList = assignTaskMapper.selectList(new LambdaQueryWrapper<AssignTaskPO>()
                .eq(AssignTaskPO::getUserId, userId)
                .eq(AssignTaskPO::getIsDeleted, 0));
        List<Long> collect = assignTaskPOList.stream().map(item -> item.getDeviceId()).collect(Collectors.toList());

        List<String> deviceLabelList = new ArrayList<>();
        for (Long aLong : collect) {
            DevicePO device = deviceMapper.selectOne(new LambdaQueryWrapper<DevicePO>()
                    .eq(DevicePO::getId, aLong)
                    .eq(DevicePO::getIsDeleted, DeviceEnums.NORMAL.getCode()));
            deviceLabelList.add(device.getLabel());
        }

        Calendar cal = Calendar.getInstance();
        //获取年份
        int year = cal.get(Calendar.YEAR);
        //获取月份
        int month = cal.get(Calendar.MONTH) + 1;
        //获取当前月最第一天
        String firstDayOfMonth = DeviceServiceImpl.getFirstDayOfMonth(month);
        //获取当前月最后一天
        String lastDayOfMonth = DeviceServiceImpl.getLastDayOfMonth(month);
        String format = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Timestamp firstTimestamp = new Timestamp(sdf.parse(firstDayOfMonth).getTime());
        Timestamp lastTimestamp = new Timestamp(sdf.parse(lastDayOfMonth).getTime());

        List<String> recordList = taskRecordMapper.selectLabelByUserId(userId,firstTimestamp,lastTimestamp);

        List<String> labelList = new ArrayList<>();
        labelList.addAll(deviceLabelList);
        labelList.addAll(recordList);
        deviceLabelList.retainAll(recordList);//找出两个集合中重复的数据
        labelList.removeAll(deviceLabelList);//然后移除

        List<DeviceVO> deviceVOList = new ArrayList<>();
        for (String label : labelList) {
            DeviceVO deviceVO = deviceMapper.selectDeviceByLabel(label);
            deviceVOList.add(deviceVO);
        }

        SysParamsPO sysParams = sysParamsMapper.selectOne(new LambdaQueryWrapper<SysParamsPO>()
                .eq(SysParamsPO::getId, 1));

        //获取当前调用接口的时间
        Date date = new Date();
        long time = date.getTime();
        String nowDateTime = DeviceServiceImpl.longToDate(time);
        Timestamp nowDate = new Timestamp(sdf.parse(nowDateTime).getTime());
        //拼接得到每个月的结束时间
        String endDateTime = year + "-" + month + "-" + sysParams.getCheckDay() + " " + "23:59:59";
        Timestamp endDate = new Timestamp(sdf.parse(endDateTime).getTime());
        //拼接得到每个月的提前提醒时间
        String remindDateTime = year + "-" + month + "-" + sysParams.getRemindDay() + " " + "00:00:00";
        Timestamp remindDate = new Timestamp(sdf.parse(remindDateTime).getTime());

        if (!CollectionUtils.isEmpty(deviceVOList) && nowDate.before(endDate) && nowDate.after(remindDate)) {
            for (DeviceVO deviceVO : deviceVOList) {
                deviceVO.setIsRemind(1);
            }
        } else if (!CollectionUtils.isEmpty(deviceVOList) && nowDate.after(lastTimestamp)){
            for (DeviceVO deviceVO : deviceVOList) {
                deviceVO.setIsRemind(2);
            }
        }

        return deviceVOList;
    }

    // 将long类型转为时间戳
    public static String longToDate(long lo) {
        Date date = new Date(lo);
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sd.format(date);
    }


    /**
     * 导入Excel表格并解析入库
     * @param filePath
     * @return
     */
    @Override
    public String importFile(String filePath) throws ParseException {
        List<List<String>> resultList = ExcelUtil.readExcel(filePath);
        for (int i = 1; i < resultList.size(); i++) {
            System.out.print("第" + (i) + "行");
            List<String> cellList = resultList.get(i);

            //数量
            String count = cellList.get(6);
            //设备类别表 （device_category）
            String type = cellList.get(0);
            String name = cellList.get(1);
            String unit = cellList.get(5);
            //设备表（device）
            String model = cellList.get(2);
            String manufacturer = cellList.get(3);
            String purchaseAt = cellList.get(4);
            String storePlace = cellList.get(7);

            if(!StringUtils.hasLength(count)) {
                return "数量不能为空";
            }
            if(!StringUtils.hasLength(type)) {
                return "设备类别不能为空";
            }
            if(!StringUtils.hasLength(name)) {
                return "设备名称不能为空";
            }
            if(!StringUtils.hasLength(unit)) {
                return "计量单位不能为空";
            }
            if(!StringUtils.hasLength(model)) {
                return "设备型号不能为空";
            }
            if(!StringUtils.hasLength(manufacturer)) {
                return "生产厂家不能为空";
            }
            if(!StringUtils.hasLength(purchaseAt)) {
                return "购买时间不能为空";
            }
            if(!StringUtils.hasLength(storePlace)) {
                return "存放地点不能为空";
            }

            //处理 类别 type
            Long typeId;
            TypePO typePO = new TypePO();
            TypePO typePO1 = typeMapper.selectOne(new LambdaQueryWrapper<TypePO>()
                    .eq(TypePO::getName, type)
                    .eq(TypePO::getIsDeleted, TypeEnums.NORMAL.getCode()));
            //若为空，则新增，然后获取ID
            if (null == typePO1) {
                typePO.setName(type);
                typePO.setIsDeleted(TypeEnums.NORMAL.getCode());
                typePO.setCreateAt(DateUtils.getCurrentTimestamp());
                typePO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
                typeMapper.insert(typePO);
                typeId = typePO.getId();
            } else {
                //不为空，则取存在的ID
                typeId = typePO1.getId();
            }

            //处理 存放地点 storePlace
            //1、拆分表格中的存放地点
            Long storePlaceId = null;
            String[] strArr = storePlace.split("-");
            int length = strArr.length;
            for (int j = 0; j < length; j++) {
                String placeName = strArr[j];
                CheckLocationPO checkLocation = checkLocationMapper.selectOne(new LambdaQueryWrapper<CheckLocationPO>()
                        .eq(CheckLocationPO::getName, placeName)
                        .eq(CheckLocationPO::getParentId, j)
                        .eq(CheckLocationPO::getIsDeleted, 0));
                //2、若没查到，则新增
                if (null == checkLocation) {
                    CheckLocationPO checkLocationPO = new CheckLocationPO();
                    checkLocationPO.setParentId(Long.valueOf(j));
                    checkLocationPO.setName(placeName);
                    checkLocationPO.setSeq(j);
                    checkLocationPO.setIsSubset(false);
                    checkLocationPO.setIsDeleted(0);
                    checkLocationPO.setCreateAt(DateUtils.getCurrentTimestamp());
                    checkLocationPO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
                    checkLocationPO.setStatus(0);
                    checkLocationMapper.insert(checkLocationPO);
                    storePlaceId = checkLocationPO.getId();
                    //修改上级的子集状态
                    if (j != 0 ) {
                        CheckLocationPO checkLocationPO1 = new CheckLocationPO();
                        Long parentId = checkLocationPO.getParentId();
                        checkLocationPO1.setId(parentId);
                        checkLocationPO1.setIsSubset(true);
                        checkLocationMapper.updateById(checkLocationPO1);
                    }
                } else {
                    //查到了，则直接赋值
                    storePlaceId = checkLocation.getId();
                }
            }

            //开始处理 所有数据
            //1、处理 device_category 的数据
            //判断是否存在
            DeviceCategoryPO deviceCategory = deviceCategoryMapper.selectOne(new LambdaQueryWrapper<DeviceCategoryPO>()
                    .eq(DeviceCategoryPO::getTypeId, typeId)
                    .eq(DeviceCategoryPO::getName, name)
                    .eq(DeviceCategoryPO::getUnit, unit));
            Long deviceCategoryId ;
            //1.1、不存在，则新增
            if (null == deviceCategory) {
                DeviceCategoryPO deviceCategoryPO = new DeviceCategoryPO();
                deviceCategoryPO.setTypeId(typeId);
                deviceCategoryPO.setName(name);
                deviceCategoryPO.setUnit(unit);
                deviceCategoryPO.setIsDeleted(0);
                deviceCategoryPO.setCreateAt(DateUtils.getCurrentTimestamp());
                deviceCategoryPO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
                deviceCategoryMapper.insert(deviceCategoryPO);
                deviceCategoryId = deviceCategoryPO.getId();
            } else {
                //1.2、存在，则直接赋值
                deviceCategoryId = deviceCategory.getId();
            }

            //2、处理 device 的数据
            List<DevicePO> devicePOList = new ArrayList<>();
            Double aDouble = Double.valueOf(count);
            int i1 = aDouble.intValue();
            for (int j = 0; j < i1; j++) {
                //设备唯一标识生成规则
                String label = UUID.randomUUID().toString().replaceAll("-", "");
                String format = "yyyy-MM-dd HH:mm:ss";
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                Timestamp timestamp = new Timestamp(sdf.parse(purchaseAt).getTime() );

                DevicePO devicePO = new DevicePO();
                devicePO.setDeviceCategoryId(deviceCategoryId);
                devicePO.setLabel(label);
                devicePO.setModel(model);
                devicePO.setManufacturer(manufacturer);
                devicePO.setStorePlaceId(storePlaceId);
                devicePO.setPurchaseAt(timestamp);
                devicePO.setIsDeleted(0);
                devicePO.setCreateAt(DateUtils.getCurrentTimestamp());
                devicePO.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
                devicePOList.add(devicePO);
            }
            this.saveBatch(devicePOList);
        }
        return "success";
    }

    /**
     * 获取当前月第一天
     * @param month
     * @return
     */
    public static String getFirstDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDay1 = sdf.format(calendar.getTime())+" 00:00:00";
        return firstDay1;
    }

    //获取当前月最后一天：
    public static String getLastDayOfMonth(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int maxDay = 0;
        //2月的平年瑞年天数
        if(month==2) {
            maxDay = calendar.getLeastMaximum(Calendar.DAY_OF_MONTH);
        }else {
            maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, maxDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String lastDay = sdf.format(calendar.getTime())+" 23:59:59";

        return lastDay;
    }
}

